/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package main.NER.Trie;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.TreeMap;
import main.Weighting.WeightingScore;
import main.initiate.UTEES_Index;

/**
 *
 * @author Isaac Osesina
 */
public class CandidateExtractorUtil {
    
    
    public static List<NER_Candidate> removeInterceptCandidateValue(List<NER_Candidate> candidates) {
        candidates = sortCandidatesByStartPos(candidates, false);
        ArrayList<NER_Candidate> out = new ArrayList<NER_Candidate>();
        for(NER_Candidate c:candidates) {
            if(!intersectsWith(c, out)) {
                out.add(c);
            }
        }
        return out;
    }

    public static boolean intersectsWith(NER_Candidate c, ArrayList<NER_Candidate> out) {
        for(NER_Candidate c1:out) {
            if(c.intersectsWith(c1)) {
                return true;
            }
        }
        return false;
    }
    
    public static List<NER_Candidate> sortCandidatesByStartPos(List<NER_Candidate> candidates, boolean ascending) {
        TreeMap<Integer, NER_Candidate> m = new TreeMap<Integer, NER_Candidate>();
        for(NER_Candidate c:candidates) {
            m.put(c.getStartPos(), c);
        }
        List<Integer> startPos = new ArrayList<Integer>(m.keySet());
        if(!ascending)
            Collections.reverse(startPos);
        candidates.clear();
        for(int s:startPos) {
            candidates.add(m.get(s));
        }
        return candidates;
    }
    
    public static String restoreTestDocument(String workingTestDoc, List<NER_Candidate> candidates) {
        boolean isTagged = UTEES_Index.isTaggedText(workingTestDoc);
        while(isTagged) {
            int start = workingTestDoc.indexOf(UTEES_Index.TAG_START_INDICATOR);
            int end = workingTestDoc.indexOf(UTEES_Index.TAG_END_INDICATOR, start);
            NER_Candidate cand = null;
            for(NER_Candidate c1:candidates) {
                if(c1.getStartPos()==start) {
                    cand = c1;
                    break;
                }
            }
            if(cand !=null) {
                workingTestDoc = workingTestDoc.substring(0, start) + cand.getEntityValue() + workingTestDoc.substring(end+1);
            }
            else {
                break;
            }
            isTagged = UTEES_Index.isTaggedText(workingTestDoc);
        }
        return workingTestDoc;
    }

    public static String tagTestDocument(String originalDoc, List<NER_Candidate> candidates) {
        String workingTestDoc = originalDoc;
        if(!candidates.isEmpty()) {
            candidates = CandidateExtractorUtil.sortCandidatesByStartPos(candidates, false);
            for(NER_Candidate c:candidates) {
                workingTestDoc = workingTestDoc.substring(0, c.getStartPos()) + UTEES_Index.tag(c.getEntityName()) + workingTestDoc.substring(c.getEndPos()+1);
            }
        }
        return workingTestDoc;
    }
    
    

    public static NER_Candidate restoreRealLeftContext(String originalDoc, NER_Candidate candidate, List<NER_Candidate> candidates) {
        String realLeft = candidate.getNewLeft().getValue();
        if( UTEES_Index.isTaggedText(realLeft) ) {
            String preContext = originalDoc.substring(0, candidate.getStartPos());
            preContext = CandidateExtractorUtil.restoreTestDocument(preContext, candidates);
            int realContextStart = preContext.length();
            String preEntityVal = preContext + realLeft;
            preEntityVal = CandidateExtractorUtil.restoreTestDocument(preEntityVal, candidates);
            realLeft = preEntityVal.substring(realContextStart);
        }
        candidate.setRealLeft(realLeft);
        return candidate;
    }


    public static NER_Candidate restoreRealRightContext(String originalDoc, NER_Candidate candidate, List<NER_Candidate> candidates) {
        String realRight = candidate.getNewRight().getValue();
        if(UTEES_Index.isTaggedText(realRight)) {
            String preContext = originalDoc.substring(0, candidate.getRightContextStart());
            preContext = CandidateExtractorUtil.restoreTestDocument(preContext, candidates);
            String withContext = preContext + realRight;
            withContext = CandidateExtractorUtil.restoreTestDocument(withContext, candidates);
            realRight = withContext.substring(candidate.getRightContextStart());
        }
        candidate.setRealRight(realRight);
        return candidate;
    }

    
    public static NER_Candidate adjustNERIndex(String originalDoc, NER_Candidate candidate, String workingTestDoc, List<NER_Candidate> candidates) {
        candidate = adjustStartEnd(workingTestDoc, candidate, candidates);
        candidate = restoreRealLeftContext(originalDoc, candidate, candidates);
        candidate = restoreRealRightContext(originalDoc, candidate, candidates);
        return candidate;
    }

    public static NER_Candidate adjustStartEnd(String workingTestDoc,NER_Candidate candidate, List<NER_Candidate> candidates) {
        String preString = workingTestDoc.substring(0, candidate.getStartPos());
        String restoreTestDocument = CandidateExtractorUtil.restoreTestDocument(preString, candidates);
        int updateCandPos = restoreTestDocument.length();
        int newEnd = updateCandPos + candidate.getEntityValue().length()-1;
        candidate.setStartPos(updateCandPos);
        candidate.setEndPos(newEnd);
        candidate.setLeftContextEnd(updateCandPos-1);
        candidate.setRightContextStart(newEnd+1);
        return candidate;
    }
    
    
    
    public static int findMaxCandidate(List<NER_Candidate> extractCandidates, List<NER_Candidate> candidates, String workingTestDoc) {
        double maxScore = -1.0;
        int maxIndex = -1;
        double candidateScore;
        for (int j=0; j<extractCandidates.size(); j++)
        {
            NER_Candidate candidate = extractCandidates.get(j);
            if(!candidate.isDeleted())
            {
                candidateScore = candidate.getScore();
                //candidate = adjustNERIndex(candidate, workingTestDoc, candidates);
                if(candidateScore>maxScore)// && !isContextInterSect(candidate, candidates) )
                {
                    maxScore = candidateScore;
                    maxIndex = j;
                }
                else if(candidateScore==maxScore)
                {
                    if(maxIndex>-1)
                    {
                        NER_Candidate maxCand = extractCandidates.get(maxIndex);
                        boolean findMaxCand2 = findMaxCandidate2(maxCand, candidate);
                        if(findMaxCand2)
                        {
                            maxScore = candidateScore;
                            maxIndex = j;
                        }
                    }
                }
            }
        }
        return maxIndex;
    }

    public static boolean findMaxCandidate2(NER_Candidate maxCandidate, NER_Candidate candidate)
    {
        WeightingScore maxWeig = maxCandidate.getWeightingScore();
        WeightingScore candWeig = candidate.getWeightingScore();
        boolean out;
        if(out = candWeig.getContextualScore() > maxWeig.getContextualScore())
            return out;
        else if(out = candWeig.getContextualScore() < maxWeig.getContextualScore())
            return !out;
        //if I put else here it is difficult to determine which of LCxt and RCxt to give preference
        
        if(out = candWeig.getIntrinsicScore() > maxWeig.getIntrinsicScore())
            return out;
        else if(out = candWeig.getIntrinsicScore() < maxWeig.getIntrinsicScore())
            return !out;
        else {
            int maxCandLen = maxCandidate.getEntityValue().length();
            int candLen = candidate.getEntityValue().length();
            out = candLen > maxCandLen;
            return out;
        }
//        return out;
    }


    public static boolean isContextInterSect(NER_Candidate candidate, List<NER_Candidate> candidates) {
        boolean intersect = false;
        for(NER_Candidate c:candidates) {
            intersect = c.isContextIntersect(candidate);
            if(intersect) {
                break;
            }
        }
        return intersect;
    }

    public static ArrayList<NER_Candidate> markIntersectCand(ArrayList<NER_Candidate> candidateList, int maxIndex)
    {
        if(candidateList.size()< 1 && maxIndex>=0)
        {
            return candidateList;
        }

        NER_Candidate maxCandidate = candidateList.get(maxIndex);
        for(int j=0; j<candidateList.size(); j++)
        {
            if(j == maxIndex)
            {
                continue;
            }
            NER_Candidate candidate = candidateList.get(j);

            if(!candidate.isDeleted() && candidate.intersectsWith(maxCandidate))
            {
                candidate.markAsDeleted();
            }
         }

        return candidateList;
    }
    
    
    

    public static List<NER_Candidate> removeCandidateWithContextIntercept(String originalDoc, List<NER_Candidate> extractCandidates, List<NER_Candidate> candidates, String workingTestDoc) {
        List<NER_Candidate> out = new ArrayList<NER_Candidate>();
        for(NER_Candidate c:extractCandidates) {
            c = CandidateExtractorUtil.adjustNERIndex(originalDoc, c, workingTestDoc, candidates);
            if(!CandidateExtractorUtil.isContextInterSect(c, candidates)) {
                out.add(c);
            }
        }
        return out;
    }
    
}
